﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntityDataModel;

namespace DataAccessLayer
{
    public class FriendshipDAL
    {
        public static String FriendshipRequest
        {
            get { return _friendshipRequest; }
            set { _friendshipRequest = value; }
        }
        private static String _friendshipRequest = "[FriendshipRequest]";

        public static String FriendshipRequestAccepted
        {
            get { return _friendshipRequestAccepted; }
            set { _friendshipRequestAccepted = value; }
        }
        private static String _friendshipRequestAccepted = "[RequestAccepted]";

        /// <summary>     
        /// Get all friends for user
        /// </summary>
        public static List<User> GetAllFriendsForUser(String userName)
        {
            using (liveCPEEntities context = new liveCPEEntities())
            {
                try
                {
                    List<Friendship> friendship = (from f in context.Friendships where f.User1Name.ToLower() == userName.ToLower() | f.User2Name.ToLower() == userName.ToLower() select f).ToList();
                    IEnumerable<User> firstUsers = (from f in friendship where f.User2Name.ToLower() != userName.ToLower() select f.User1);
                    List<User> allUsers = (from f in friendship where f.User1Name.ToLower() != userName.ToLower() select f.User).Union(firstUsers).ToList();
                    return allUsers;
                }
                catch (Exception e)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
                    LogDAL.AddLog(e.Message, "Error", DataAccessLayerSettings.Default.ApplicationName, sf.GetMethod().Name, DateTime.Now);
                    throw new Exception(sf.GetMethod().Name + " unexpected error", e);
                }
            }
        }

        /// <summary>     
        /// Return true if the given users are friends
        /// </summary>
        public static Boolean AreTheyFriends(String userName1, String userName2)
        {
            using (liveCPEEntities context = new liveCPEEntities())
            {
                try
                {
                    IQueryable<Friendship> friends = from f in context.Friendships where ((f.User1Name == userName1 & f.User2Name == userName2) | (f.User1Name == userName2 & f.User2Name == userName1)) & f.IsActive == true select f;
                    if (friends.ToList().Count > 0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
                    LogDAL.AddLog(e.Message, "Error", DataAccessLayerSettings.Default.ApplicationName, sf.GetMethod().Name, DateTime.Now);
                    throw new Exception(sf.GetMethod().Name + " unexpected error", e);
                }
            }
        }

        /// <summary>     
        /// Create a friendship between two users
        /// </summary>
        public static Boolean CreateFriendship(string userName1, string userName2)
        {
            using (liveCPEEntities context = new liveCPEEntities())
            {
                try
                {
                    Guid friendshipId = System.Guid.NewGuid();
                    IQueryable<Friendship> friends = from f in context.Friendships where ((f.User1Name == userName1 & f.User2Name == userName2) | (f.User1Name == userName2 & f.User2Name == userName1)) & f.IsActive == false select f;

                    // If there is no pending friendship request
                    if (friends.ToList().Count == 0)
                    {
                        context.Friendships.AddObject(new Friendship
                        {
                            FriendshipID = friendshipId,
                            User1Name = userName1,
                            User2Name = userName2,
                            QueryDate = DateTime.Now,
                            IsActive = false
                        });

                        Guid notificationId = System.Guid.NewGuid();
                        context.Notifications.AddObject(new Notification
                        {
                            NotificationID = notificationId,
                            UserName = userName2,
                            FriendShipID = friendshipId,
                            PublicationDate = DateTime.Now
                        });

                        Guid messageId = System.Guid.NewGuid();
                        context.Messages.AddObject(new Message
                        {
                            MessageID = messageId,
                            SenderName = userName1,
                            ReceiverName = userName2,
                            NumLike = 0,
                            PublicationDate = DateTime.Now,
                            IsPrivate = false,
                            IsVisible = true,
                            MessageContent = FriendshipRequest
                        });

                        context.SaveChanges();
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
                    LogDAL.AddLog(e.Message, "Error", DataAccessLayerSettings.Default.ApplicationName, sf.GetMethod().Name, DateTime.Now);
                    throw new Exception(sf.GetMethod().Name + " unexpected error", e);
                }
            }
        }

        /// <summary>     
        /// Accept a friendship request
        /// </summary>
        public static void AcceptFriendship(Message msg)
        {
            using (liveCPEEntities context = new liveCPEEntities())
            {
                try
                {
                    Message message = (from m in context.Messages where m.MessageID == msg.MessageID select m).First();
                    if (message != null)
                    {
                        String senderName = message.SenderName;
                        String receiverName = message.ReceiverName;
                        Friendship friend = (from f in context.Friendships where ((f.User1Name == senderName & f.User2Name == receiverName) | (f.User1Name == receiverName & f.User2Name == senderName)) & f.IsActive == false select f).First();
                        
                        if (friend != null)
                        {
                            // Validate the friendship request
                            friend.ValidationDate = DateTime.Now;
                            friend.IsActive = true;

                            // Inform the request sender that the request is validated 
                            Guid messageId = System.Guid.NewGuid();
                            context.Messages.AddObject(new Message
                            {
                                MessageID = messageId,
                                SenderName = message.ReceiverName,
                                ReceiverName = message.SenderName,
                                PublicationDate = DateTime.Now,
                                MessageContent = FriendshipRequestAccepted,
                                NumLike = 0,
                                IsPrivate = false,
                                IsVisible = true
                            });

                            // Create a notification
                            Guid notificationId = System.Guid.NewGuid();
                            context.Notifications.AddObject(new Notification
                            {
                                NotificationID = notificationId,
                                UserName = message.SenderName,
                                FriendShipID = friend.FriendshipID,
                                PublicationDate = DateTime.Now
                            });

                            Notification notification = (from n in context.Notifications where n.FriendShipID == friend.FriendshipID select n).First();
                            
                            context.DeleteObject(notification);
                            context.DeleteObject(message);
                            context.SaveChanges();
                        }
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
                    LogDAL.AddLog(e.Message, "Error", DataAccessLayerSettings.Default.ApplicationName, sf.GetMethod().Name, DateTime.Now);
                    throw new Exception(sf.GetMethod().Name + " unexpected error", e);
                }
            }
        }

        /// <summary>     
        /// Reject a friendship request
        /// </summary>
        public static void RejectFriendship(Message msg)
        {
            using (liveCPEEntities context = new liveCPEEntities())
            {
                try
                {
                    Message message = (from m in context.Messages where m.MessageID == msg.MessageID select m).First();
                    if (message != null)
                    {
                        String senderName = message.SenderName;
                        String receiverName = message.ReceiverName;
                        Friendship friend = (from f in context.Friendships where ((f.User1Name == senderName & f.User2Name == receiverName) | (f.User1Name == receiverName & f.User2Name == senderName)) & f.IsActive == false select f).First();

                        if (friend != null)
                        {
                            // Validate the friendship request
                            friend.IsActive = false;

                            context.DeleteObject(message);
                            context.SaveChanges();
                        }
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame();
                    LogDAL.AddLog(e.Message, "Error", DataAccessLayerSettings.Default.ApplicationName, sf.GetMethod().Name, DateTime.Now);
                    throw new Exception(sf.GetMethod().Name + " unexpected error", e);
                }
            }
        }
    }
}
